/*
 * Dcm_UDS0x37.c
 *
 *  Created on: 2018-8-21
 *      Author: tao.yu
 */

#include "UDS.h"


/****************************************************************
     UDS: RequestDownload (37 hex) service
 ***************************************************************/
#if (STD_ON == DCM_UDS_SERVICE0X37_ENABLED)
/***************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x37ServiceConditionCheck(
        uint8 ProtocolCtrlId,
        uint8 MsgCtrlId)
{
    Std_ReturnType ret = E_OK;

    /*************************************************/
#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    /*session check,check whether the current
     * session supports the request service*/
    ret = DsdInternal_SesCheck(ProtocolCtrlId,
            SID_REQUEST_TRANSFER_EXIT);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-073[DCM211]****/
        /*the current session does not support
         * the request service,send NRC = 0x7F*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif

    /*************************************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    /*security check,check whether the
     * current security supports the request service*/
    ret = DsdInternal_SecurityCheck(ProtocolCtrlId,
            SID_REQUEST_TRANSFER_EXIT);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-074[DCM217]****/
        /*the current security does not support
         * the request service,send NRC = 0x33*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_SECURITYACCESSDENIED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif
    return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"


/*******************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x37(
        Dcm_OpStatusType OpStatus,
        uint8  ProtocolCtrlId,
        P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
    uint8  MsgCtrlId = 0u;
    Std_ReturnType ret = E_OK;
    uint8  TxChannelCtrlIndex = 0u;
    uint8  TxChannelCfgIndex = 0u;
    uint16 Offset = 0u;
    uint32 transferRequestParameterRecordSize = 0;
    uint32 transferResponseParameterRecordSize = 0;
    uint8* transferRequestParameterRecord;
    uint8* transferResponseParameterRecord;

    /*************************************************/
    /*if the required protocol is configured,get the index of runtime datum*/
    MsgCtrlId =  Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;

    /*************************************************/
    ret = Dcm_Uds0x37ServiceConditionCheck(ProtocolCtrlId, MsgCtrlId);
    if(E_OK != ret)
    {
     return ret;
    }

    TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
    TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
    Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

    transferRequestParameterRecordSize = Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen - 1u;
    transferRequestParameterRecord = &(Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[1]);
    transferResponseParameterRecord = &Dcm_Channel[Offset + 1u];

    /*[SWS_Dcm_01134] Following NRC will be the responsibility of the callout function
     * 0x13,0x24,0x31,0x72*/
    ret = Dcm_ProcessRequestTransferExit(OpStatus,
                                        transferRequestParameterRecord,
                                        transferRequestParameterRecordSize,
                                        transferResponseParameterRecord,
                                        &transferResponseParameterRecordSize,
                                        ErrorCode);
    if (E_NOT_OK == ret)
    {/*[SWS_Dcm_00759] */
        /*the processing is not successful,send NRC */
        (void)DsdInternal_SetNrc(ProtocolCtrlId, *ErrorCode);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
    else if (DCM_E_PENDING == ret)
    {
        Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
        return ret;
    }
    else
    {
        /*idle*/
    }

    /* check tx data length */
    if ((1u + transferResponseParameterRecordSize)
            > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
    {
        /*Pdu length is bigger than buffer size */
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

    /* clear address */
    Dcm_DspProgram.address = 0UL;
    /* clear index to 0*/
    Dcm_DspProgram.blockId = 0x00;
    /* clear 0x36 service status to DCM_UDS0X36_INIT*/
    Dcm_DspProgram.Status = DCM_UDS0X36_INIT;
    /*clear the MemoryIdInfoIndex*/
    Dcm_DspProgram.MemoryIdInfoIndex = 0xFF;
    /*clear one block size*/
    Dcm_DspProgram.BlockLength = 0;

    /**********************************************************
     * assemble positive response
     *********************************************************/
    /*the processing is successful,assemble positive response*/
    SchM_Enter_Dcm(Dcm_Channel);
    Dcm_Channel[Offset] = 0x77;             /*response SID*/
    SchM_Exit_Dcm(Dcm_Channel);
    SchM_Enter_Dcm(Dcm_MsgCtrl);
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen =
            1u + transferResponseParameterRecordSize;
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    =
            1u + transferResponseParameterRecordSize;
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
    SchM_Exit_Dcm(Dcm_MsgCtrl);
    DsdInternal_ProcessingDone(ProtocolCtrlId);

    return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

#endif
